---
title: PdfAPI.SyncFusionCore architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-17
library: PdfAPI.SyncFusionCore
reference_type: package
---

# PdfAPI.SyncFusionCore architecture

`PdfAPI.SyncFusionCore` is the Syncfusion-backed PDF engine of the IT.CoreServices.PDFAPI repository: it converts source documents of several formats to PDF/PDF-A, extracts page ranges, merges documents, flattens form fields, and registers the Syncfusion runtime license. It is a class library with no program entry point — the repository's top-level Web API project (`PdfAPI`) is the consumer that dispatches to it — and it performs no database access and no authorization work.

## Responsibilities
- Dispatch a conversion request to the converter matching the source file extension
  (`ConverterFactory`).
- Convert eight source formats (Word, Excel, RTF, plain text, image, TIFF, HTML, PDF) to PDF or
  PDF/A via format-specific converters built on the Syncfusion SDK.
- Extract selected page ranges from a source PDF into a new PDF (`PdfExtractor`), including
  ascending/descending ranges and open-ended stop pages.
- Merge multiple document ranges into a single PDF, optionally at PDF/A conformance
  (`PdfMerger`).
- Inspect and flatten AcroForm fields in a PDF, and build `ApplicationExceptionDetail` diagnostic
  records for callers (`PdfHelper`).
- Register the Syncfusion runtime license once per process (`LicenseHelper`).

## Component boundaries
- **Dispatch (`ConverterFactory`)**: extension-to-converter routing; recursion for the text →
  PDF/A path; returns a non-throwing result for an unmatched extension.
- **Conversion template (`BaseConverter`)**: cross-cutting conversion concerns — stream disposal,
  a per-format `ConfigureConverter` hook, stopwatch timing, exception capture, `PdfResult` assembly, and processor stamping. Note: this type is physically compiled into `PdfAPI.SyncFusionCore` but declares the namespace `PdfAPI.Core.Convert`, so consumers that reference only `PdfAPI.Core` cannot see it.
- **Conversion implementations (`WordConverter`, `ExcelConverter`, `RtfConverter`,
  `TxtConverter`, `ImageConverter`, `TiffConverter`, `HtmlConverter`, `PdfConverter`)**:
  format-specific byte-array production via the Syncfusion API; each implements `ConvertItem`/`ConfigureConverter` under the `BaseConverter` template.
- **Page composition (`PdfExtractor`, `PdfMerger`)**: page-range extraction and multi-document
  merge, both with optional PDF/A conformance. `PdfMerger` is the library's only constructor- injected type (`IEnvironmentService`, `ILogService`), constructed directly by the caller (`new PdfMerger(environmentService, logService)`), not via a DI container.
- **Utilities (`PdfHelper`, `LicenseHelper`)**: AcroForm inspection/flattening, exception-detail
  construction, and Syncfusion license registration.
- **Contract boundary (`PdfAPI.Core`)**: the library's only internal dependency, supplying the
  request/result contracts (`ConvertRequest`, `MergeRequest`, `ExtractPagesRequest`, `PdfRequest`, `PdfResult`, `PdfOptions`, `Document`, `DocumentRange`, `PageRange`, and related enums).

## Interaction model
- All inputs arrive as in-memory `byte[]` (via `ConvertRequest.File`, `Document.File`) and all
  outputs are produced as `byte[]` wrapped into a `PdfAPI.Core.Document`; the library never writes to disk itself, except that `PdfMerger` calls `range.Document.Load()`, which may read a range's source file from `FilePath` on disk when in-memory bytes are absent.
- `ConverterFactory.Convert` is the single entry point for format conversion: it normalizes the
  file extension, constructs the matching converter, and delegates to `BaseConverter.Convert`, which in turn calls the converter's `ConvertItem`. A successful text conversion is recursively resubmitted through the PDF path so PDF/A can be applied uniformly.
- `PdfExtractor.Extract` is called both directly by callers and internally by `PdfMerger` when a
  document range is partial or spans multiple page ranges.
- `PdfMerger.Merge` loads each document range, extracts subsets where needed via
  `PdfExtractor.Extract`, merges the resulting documents with `Syncfusion.Pdf.PdfDocument.Merge`, and optionally performs a post-merge PDF/A upgrade pass; failures in that upgrade pass are logged via `ILogService` (`SAIF.Framework.Core`) rather than thrown.
- Failure handling is asymmetric by design: `BaseConverter.Convert` catches every exception and
  returns a failed `PdfResult`, whereas `PdfExtractor.Extract` and the primary merge path let exceptions propagate to the caller.
- `LicenseHelper.LicenseSyncfusion()` must be invoked once per process before any Syncfusion API
  use; in this repository it is called from `PdfAPI\Global.asax.cs` (`Application_Start`).
- The library is consumed both as a project reference by the `PdfAPI` Web API
  (`SyncfusionPdfService`, `PdfService`) and, packaged as the `Pdf.Local.Client` NuGet package (together with `PdfAPI.Core`), by external NuGet consumers.

## Architecture diagram
The following diagram shows high-level component interactions.

```mermaid
flowchart LR
  API["PdfAPI (ASP.NET Web API)<br>SyncfusionPdfService, PdfService"] --> SFC["PdfAPI.SyncFusionCore<br>ConverterFactory, PdfMerger,<br>PdfExtractor, PdfHelper"]
  SFC --> Core["PdfAPI.Core<br>request/result contracts"]
  SFC --> SF["Syncfusion 18.3<br>Pdf / DocToPDF / ExcelToPdf /<br>HtmlToPdf / Licensing"]
  SFC --> FW["SAIF.Framework.Core + Common<br>ILogService, IEnvironmentService"]
  API --> Core
```

## Sequence diagram
The following diagram shows the primary request/response sequence for a document conversion.

```mermaid
sequenceDiagram
	participant Client as PdfAPI (SyncfusionPdfService)
	participant Factory as ConverterFactory
	participant Base as BaseConverter
	participant SF as Syncfusion SDK
	Client->>Factory: Convert(ConvertRequest)
	Factory->>Base: new matching converter (e.g. WordConverter), Convert(stream, request)
	Base->>SF: ConvertItem(stream, request)
	SF-->>Base: converted bytes
	Base-->>Factory: PdfResult (Status, Elapsed, Document)
	Factory-->>Client: PdfResult
```

## Design constraints
- `BaseConverter` declares namespace `PdfAPI.Core.Convert` while being compiled into
  `PdfAPI.SyncFusionCore`, so consumers referencing only `PdfAPI.Core` cannot resolve it — likely the result of a prior move between projects that left the namespace unchanged.*
- `ConfigureConverter(PdfOptions)` is an abstract per-format hook that every one of the eight
  converters implements as an empty method, making the hook currently inert.
- `ConverterFactory.Convert` is a simple factory with a `switch`; adding a new format requires
  editing the switch, as there is no registry or discovery by `ConversionType`.
- Static-utility classes (`ConverterFactory`, `PdfExtractor`, `PdfHelper`, `LicenseHelper`) expose
  only static methods but are declared as ordinary (non-static) public classes and can be instantiated.
- `PdfMerger` is the only type with constructor-injected dependencies
  (`IEnvironmentService`, `ILogService`); it is constructed directly with `new PdfMerger(environmentService, logService)` by the caller rather than resolved through Autofac.
- The library reads no application configuration itself (no `ConfigurationManager`/`AppSettings`
  usage); all behavior is driven by the `PdfAPI.Core` request objects passed in by the caller. Its `app.config` carries only assembly binding redirects, whose targets (`18.3460.0.35`) are lower than the Syncfusion/RestSharp versions actually referenced — the file appears stale relative to the package set.*
- The library performs no authentication or authorization work; access control for these
  operations is entirely the responsibility of the hosting `PdfAPI` application.
- Six referenced packages (`Autofac`, `FluentValidation`, `log4net`, `RestSharp`,
  `SAIF.Web.API.Clients`, `SAIF.HashUtil`) have no corresponding usage in this library's source and appear to be carried over from a shared reference set.*
- The `Pdf.Local.Client` nuspec pins Syncfusion dependencies at 17.4.0.46 while the project builds
  against 18.3.0.53, and declares an unused `iTextSharp` 5.5.11 dependency; it also omits the `SAIF.Framework.Core`/`SAIF.Framework.Common` dependencies required at run time.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [API reference](api/index.md)
- [PdfAPI.Core overview](../pdfapi-core/overview.md)

> **Note:** Statements marked with * were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts.

## Sources
- `PdfApi.SyncFusionCore\PdfAPI.SyncFusionCore.csproj`
- `PdfApi.SyncFusionCore\packages.config`
- `PdfApi.SyncFusionCore\app.config`
- `PdfApi.SyncFusionCore\LicenseHelper.cs`
- `PdfApi.SyncFusionCore\PdfHelper.cs`
- `PdfApi.SyncFusionCore\Convert\BaseConverter.cs`
- `PdfApi.SyncFusionCore\Convert\ConverterFactory.cs`
- `PdfApi.SyncFusionCore\Convert\ExcelConverter.cs`
- `PdfApi.SyncFusionCore\Convert\HtmlConverter.cs`
- `PdfApi.SyncFusionCore\Convert\ImageConverter.cs`
- `PdfApi.SyncFusionCore\Convert\PdfConverter.cs`
- `PdfApi.SyncFusionCore\Convert\RtfConverter.cs`
- `PdfApi.SyncFusionCore\Convert\TiffConverter.cs`
- `PdfApi.SyncFusionCore\Convert\TxtConverter.cs`
- `PdfApi.SyncFusionCore\Convert\WordConverter.cs`
- `PdfApi.SyncFusionCore\Extract\PdfExtractor.cs`
- `PdfApi.SyncFusionCore\Merge\PdfMerger.cs`
- `PdfAPI\Services\Syncfusion\SyncfusionPdfService.cs`
- `PdfAPI\Services\PdfService.cs`
- `PdfAPI\Global.asax.cs`
